package com.util;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;


public class AESUtil {
    /**
     * 算法模式
     */
    private static final String TRANS_FORMATION = "AES/CBC/NoPadding";

    /**
     * 算法类型
     */
    private static final String ALGORITHM_AES = "AES";

    /**
     * 默认密钥key
     */
    private static final String DEFAULT_SECRETKEY = "damingshan123456";

    /**
     * 默认向量IV
     */
    private static final String DEFAULT_IV = DEFAULT_SECRETKEY;

    /**
     * 加密
     *
     * @param data      要加密的数据
     * @param secretKey 加密key（长度必须为16）
     * @param iv        向量iv（长度必须为16）
     * @return String
     */
    public static String encrypt(String data, String secretKey, String iv) throws Exception {
        Cipher cipher = Cipher.getInstance(TRANS_FORMATION); // "算法/模式/补码方式"
        int blockSize = cipher.getBlockSize();

        byte[] dataBytes = data.getBytes();
        int plaintextLength = dataBytes.length;

        if (plaintextLength % blockSize != 0) {
            plaintextLength = plaintextLength
                    + (blockSize - (plaintextLength % blockSize));
        }

        byte[] plaintext = new byte[plaintextLength];
        System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);

        SecretKeySpec keyspec = new SecretKeySpec(secretKey.getBytes(), ALGORITHM_AES);
        IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());

        cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
        byte[] encrypted = cipher.doFinal(plaintext);

        return parseByte2HexStr(encrypted);
    }

    public static String parseByte2HexStr(byte[] buf) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; ++i) {
            String hex = Integer.toHexString(buf[i] & 255);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toLowerCase());
        }
        return sb.toString();
    }

    /**
     * 解密
     *
     * @param data      要解密的数据
     * @param secretKey 解密key
     * @param iv        向量iv
     * @return String
     */
    public static String decrypt(String data, String secretKey, String iv) throws Exception {
        byte[] encrypted = parseHexStr2Byte(data);

        Cipher cipher = Cipher.getInstance(TRANS_FORMATION);
        SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(), ALGORITHM_AES);
        IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes());

        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);

        byte[] original = cipher.doFinal(encrypted);
        return new String(original, "UTF-8").trim();
    }

    public static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1) {
            return null;
        } else {
            byte[] result = new byte[hexStr.length() / 2];

            for (int i = 0; i < hexStr.length() / 2; ++i) {
                int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
                int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
                result[i] = (byte) (high * 16 + low);
            }
            return result;
        }
    }

    /**
     * 使用默认的key和iv加密
     *
     * @param data
     * @return String
     */
    public static String encrypt(String data) throws Exception {
        return encrypt(data, DEFAULT_SECRETKEY, DEFAULT_IV);
    }

    /**
     * 使用默认的key和iv解密
     *
     * @param data
     * @return String
     */
    public static String decrypt(String data) throws Exception {
        return decrypt(data, DEFAULT_SECRETKEY, DEFAULT_IV);
    }
}
